package com.example.tomatotodo;

import static java.lang.Thread.sleep;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;

import androidx.activity.OnBackPressedCallback;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;

import com.example.tomatotodo.model.TodoConstants;
import com.example.tomatotodo.model.TodoItem;
import com.example.tomatotodo.model.TodoRecordSyncDTO;
import com.example.tomatotodo.model.TodoSettingDTO;
import com.example.tomatotodo.util.ColorUtils;
import com.example.tomatotodo.util.RecordUtil;

import java.time.LocalDateTime;

public class FocusActivity extends AppCompatActivity {

    private static final String TAG = "FocusActivity";

    private int debugTime = BuildConfig.FOCUS_DEBUG_TIME; // 调试用，用于减少时间，单位秒，实际使用请置0或负数

    private TodoRecordSyncDTO record;   // 用于存储本次专注的记录
    private TodoSettingDTO setting;     // 用于存储本次专注的设定
    private int currentCycle = 0;       // 当前的专注周期，一个周期分为两个阶段：专注阶段和休息阶段
    private int totalFocusSeconds = 0;  // 总专注时长（秒）
    private int totalRestSeconds = 0;   // 总休息时长（秒）

    private ConstraintLayout focus_root;
    private ImageButton backButton;     // 返回按钮
    private TextView statusText;        // 状态显示
    private TextView timerText;         // 计时器显示
    private TextView taskNameText;      // 任务名称显示
    private Button pauseButton;         // 暂停按钮
    private Button skipButton;          // 跳过按钮
    private Button stopButton;          // 停止按钮

    // 计时相关变量
    private Handler timerHandler = new Handler(Looper.getMainLooper());
    private Runnable timerRunnable;
    private int currentTime = 0; // 当前时间（秒）, 若为倒计时，则为倒计时剩余时间，若为正向计时，则为已专注时间，若在休息状态，则为休息剩余时间
    private boolean isRunning = false; // 计时器是否正在运行
    private boolean isFocusState = true; // true表示专注状态，false表示休息状态
    private boolean isTaskCompleted = false; // true表示任务所有周期已完成

    // 正向计时模式专用变量
    private int currentFocusSeconds = 0; // 当前专注周期已专注秒数

    // 振动器
    private Vibrator vibrator;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_focus);

        // 初始化振动器
        vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

        initViews();
        handleIntent(getIntent());
        setGradientBackground();
        setListeners();
        startTimer();
    }

    /**
     * 处理传入的Intent
     *
     * @param intent 传入的Intent
     */
    private void handleIntent(Intent intent) {
        if (intent == null) return;

        Log.d(TAG, "handleIntent: 处理传入的Intent");

        // 获取传入的设定参数
        TodoItem todoItem = (TodoItem) intent.getSerializableExtra("todo_item");
        if (todoItem == null) {
            Log.w(TAG, "handleIntent: 未获取到传入的设定参数，使用默认设定");
            setting = new TodoSettingDTO();
        } else {
            setting = todoItem.getSetting();
            taskNameText.setText(setting.getTitle()); // 显示任务名称

            // 根据计时模式设置初始时间显示
            if (TodoConstants.TIMER_MODE_COUNTDOWN.equals(setting.getTimerMode())) {
                // 倒计时模式，显示倒计时时间
                currentTime = getFocusDuration();
                timerText.setText(formatTime(currentTime));
                // 倒计时模式初始显示所有按钮
                updateButtonVisibility(true, true, true);
            } else if (TodoConstants.TIMER_MODE_UPTIME.equals(setting.getTimerMode())) {
                // 正向计时模式，初始为00:00
                timerText.setText("00:00");
                // 正向计时模式初始只显示暂停和停止按钮
                updateButtonVisibility(true, true, false);
                // 正向计时模式下，停止按钮显示"结束"
                stopButton.setText("结束");
            } else {
                timerText.setText("发生错误");
                updateButtonVisibility(false, false, false);
                return;
            }

            Log.d(TAG, "handleIntent: 成功获取到传入的设定参数\n"
                    + "\t名称: \"" + setting.getTitle() + "\"\t计时模式: \"" + setting.getTimerMode() + "\"");
        }

        // 初始化记录对象
        record = new TodoRecordSyncDTO();
        record.setClientCreatedAt(LocalDateTime.now());
        record.setStartTime(LocalDateTime.now());

        // 设置任务关联信息
        if (setting != null) {
            record.setTaskTitle(setting.getTitle());
            record.setTaskType(setting.getType());
        }

        // 如果传入的todoItem不为空，设置任务ID
        if (todoItem != null) {
            record.setTaskId(todoItem.getId());
        }

        Log.d(TAG, "handleIntent: 初始化记录对象完成");
    }

    /**
     * 初始化视图控件
     */
    private void initViews() {
        focus_root = findViewById(R.id.focus_root);
        backButton = findViewById(R.id.btn_back);
        statusText = findViewById(R.id.tv_status);
        timerText = findViewById(R.id.tv_timer);
        taskNameText = findViewById(R.id.tv_task_name);
        pauseButton = findViewById(R.id.btn_pause);
        skipButton = findViewById(R.id.btn_skip);
        stopButton = findViewById(R.id.btn_stop);
    }

    /**
     * 设置按钮监听器
     */
    private void setListeners() {
        // 返回按钮监听器
        backButton.setOnClickListener(v -> {
            Log.d(TAG, "点击返回按钮");
            handleGiveUp();
        });

        // 暂停按钮监听器
        pauseButton.setOnClickListener(v -> {
            Log.d(TAG, "点击暂停/继续按钮");
            togglePauseResume();
        });

        // 跳过按钮监听器
        skipButton.setOnClickListener(v -> {
            Log.d(TAG, "点击跳过按钮");
            handleSkip();
        });

        // 停止按钮监听器
        stopButton.setOnClickListener(v -> {
            Log.d(TAG, "点击停止按钮");
            if (isTaskCompleted) {
                handleTaskCompletion();
            } else {
                // 根据计时模式决定处理方式
                if (setting != null && TodoConstants.TIMER_MODE_UPTIME.equals(setting.getTimerMode())) {
                    handleUptimeModeStop();
                } else {
                    handleGiveUp();
                }
            }
        });

        // 返回键事件监听
        getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                Log.d(TAG, "按下返回键");
                handleGiveUp();
            }
        });
    }

    /**
     * 开始计时器
     */
    private void startTimer() {
        if (timerRunnable != null) {
            timerHandler.removeCallbacks(timerRunnable);
        }

        timerRunnable = new Runnable() {
            @Override
            public void run() {
                if (isRunning) {
                    updateTimer();
                    timerHandler.postDelayed(this, 1000); // 每秒更新一次
                }
            }
        };

        isRunning = true;
        timerHandler.postDelayed(timerRunnable, 1000);
    }

    /**
     * 更新计时器
     */
    private void updateTimer() {
        if (TodoConstants.TIMER_MODE_COUNTDOWN.equals(setting.getTimerMode())) {
            // 倒计时模式
            currentTime--;
            if (currentTime <= 0) {
                // 时间到，切换状态
                toggleState();
                // 如果任务已完成，停止计时器
                if (currentCycle >= setting.getCycle() && !isFocusState) {
                    isRunning = false;
                    timerHandler.removeCallbacks(timerRunnable);
                }
            }
        } else if (TodoConstants.TIMER_MODE_UPTIME.equals(setting.getTimerMode())) {
            // 正向计时模式
            if (isFocusState) {
                // 专注状态正向计时
                currentTime++;
                currentFocusSeconds = currentTime; // 实时更新当前周期专注时间
            } else {
                // 休息状态始终是倒计时
                currentTime--;
                if (currentTime <= 0) {
                    // 休息时间到，切换状态
                    toggleState();
                    // 如果任务已完成，停止计时器
                    if (currentCycle >= setting.getCycle() && !isFocusState) {
                        isRunning = false;
                        timerHandler.removeCallbacks(timerRunnable);
                    }
                }
            }
        }

        timerText.setText(formatTime(currentTime));
        if (currentTime < 5)
            Log.d(TAG, "updateTimer: currentTime=" + currentTime + ", 当前状态: " + (isFocusState ? "专注" : "休息"));
    }

    /**
     * 切换状态（专注/休息）
     */
    private void toggleState() {
        Log.d(TAG, "toggleState: 当前状态 isFocusState=" + isFocusState + ", currentCycle=" + currentCycle);

        // 执行过渡动画
        performTransition();

        if (isFocusState) {
            // 当前是专注状态，即将切换到休息状态
            Log.d(TAG, "toggleState: 专注阶段结束，准备进入休息阶段");

            // 记录实际专注时长
            int actualFocusDuration_cycle;
            if (TodoConstants.TIMER_MODE_COUNTDOWN.equals(setting.getTimerMode())) {
                actualFocusDuration_cycle = getFocusDuration() - currentTime;
            } else {
                actualFocusDuration_cycle = currentFocusSeconds;
            }

            // 累加专注时间
            Log.d(TAG, "toggleState: 第" + (currentCycle + 1) + "周期, 实际专注时长=" + actualFocusDuration_cycle + "秒");
            totalFocusSeconds += actualFocusDuration_cycle;

            // 切换到休息状态
            isFocusState = false;
            statusText.setText("休息中");
            currentTime = getRestDuration(); // 休息状态始终是倒计时

            // 休息状态只显示跳过按钮
            updateButtonVisibility(false, false, true);

            Log.d(TAG, "toggleState: 进入休息状态，设定休息时长=" + currentTime + "秒");
        } else {
            // 当前是休息状态，即将完成一个完整周期并切换到下一个周期的专注状态
            Log.d(TAG, "toggleState: 休息阶段结束，准备进入下一周期");

            // 记录实际休息时长（休息状态始终是倒计时）
            int actualRestDuration_cycle = getRestDuration() - currentTime;
            Log.d(TAG, "toggleState: 第" + (currentCycle + 1) + "周期, 实际休息时长=" + actualRestDuration_cycle + "秒");
            totalRestSeconds += actualRestDuration_cycle;

            // 完成一个周期（专注+休息）
            currentCycle++;
            Log.i(TAG, "toggleState: 完成第" + currentCycle + "个周期");

            // 检查是否已完成所有周期
            if (currentCycle >= setting.getCycle()) {
                // 已完成所有周期，结束任务
                Log.i(TAG, "toggleState: 所有周期已完成，任务结束");
                statusText.setText("任务完成");
                // 任务完成时隐藏暂停/继续按钮和跳过按钮
                updateButtonVisibility(false, true, false);

                stopButton.setText("完成");
                timerText.setText("完成");
                isTaskCompleted = true; // 所有周期都完成，设置为true
                // 停止计时器以防止死循环
                isRunning = false;
                timerHandler.removeCallbacks(timerRunnable);
                // TODO: 可以在这里添加任务完成的处理逻辑
                return;
            }

            // 重置实际时长记录
            currentFocusSeconds = 0;

            // 切换到专注状态
            isFocusState = true;
            statusText.setText("专注中");

            // 根据计时模式设置专注时间
            if (TodoConstants.TIMER_MODE_COUNTDOWN.equals(setting.getTimerMode())) {
                currentTime = getFocusDuration(); // 倒计时模式设置为专注时长
            } else {
                currentTime = 0; // 正向计时从0开始
            }

            updateButtonVisibility(true, true, true);

            Log.d(TAG, "toggleState: 进入第" + (currentCycle + 1) + "个周期的专注状态，设定时长=" + currentTime + "秒");
        }
    }

    /**
     * 切换暂停/继续状态
     */
    private void togglePauseResume() {
        isRunning = !isRunning;
        if (isRunning) {
            // 继续计时
            startTimer();
            pauseButton.setText("暂停");
        } else {
            // 暂停计时
            timerHandler.removeCallbacks(timerRunnable);
            pauseButton.setText("继续");
        }
    }

    /**
     * 将秒数格式化为 MM:ss 格式的时间显示
     *
     * @param seconds 总秒数
     * @return 格式化后的时间字符串
     */
    private String formatTime(int seconds) {
        int minutes = seconds / 60;
        int secs = seconds % 60;
        return String.format("%02d:%02d", minutes, secs);
    }

    /**
     * 获取专注倒计时时间（秒）<br>
     * 如果是调试模式且debugTime大于0，则返回debugTime<br>
     * 否则返回设置中的倒计时时间
     *
     * @return 倒计时时间（秒）
     */
    private int getFocusDuration() {
        if (debugTime > 0) {
            Log.d(TAG, "getFocusDuration: 【调试】倒计时时间: " + debugTime + "秒");
            return debugTime;
        }

        if (setting != null && setting.getCountdownDuration() != null) {
            Log.d(TAG, "getFocusDuration: 【正常】倒计时时间: " + setting.getCountdownDuration() + "秒");
            return setting.getCountdownDuration();
        }

        Log.d(TAG, "getFocusDuration: 【异常】倒计时时间为默认值: " + TodoConstants.DEFAULT_COUNTDOWN_DURATION + "秒");
        return TodoConstants.DEFAULT_COUNTDOWN_DURATION;
    }

    /**
     * 获取休息时间（秒）<br>
     * 如果是调试模式且debugTime大于0，则返回debugTime<br>
     * 否则返回设置中的休息时间
     *
     * @return 休息时间（秒）
     */
    private int getRestDuration() {
        if (debugTime > 0) {
            Log.d(TAG, "getRestDuration: 【调试】休息时间: " + debugTime + "秒");
            return debugTime;
        }

        if (setting != null && setting.getRestDuration() != null) {
            Log.d(TAG, "getRestDuration: 【正常】休息时间: " + setting.getRestDuration() + "秒");
            return setting.getRestDuration();
        }

        Log.d(TAG, "getRestDuration: 【异常】休息时间为默认值: " + TodoConstants.DEFAULT_REST_DURATION + "秒");
        return TodoConstants.DEFAULT_REST_DURATION;
    }

    /**
     * 设置渐变背景
     */
    private void setGradientBackground() {
        // 生成随机低饱和度颜色
        int[] colors = ColorUtils.generateRandomLowSaturationColors();
        // 获取随机渐变方向
        GradientDrawable.Orientation orientation = ColorUtils.getRandomOrientation();

        // 创建渐变背景
        GradientDrawable gradientDrawable = new GradientDrawable(
                orientation,
                colors
        );
        gradientDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);

        // 应用到背景
        focus_root.setBackground(gradientDrawable);
    }

    /**
     * 更新按钮显示
     *
     * @param pauseButtonVisible 是否显示暂停按钮
     * @param stopButtonVisible  是否显示停止按钮
     * @param skipButtonVisible  是否显示跳过按钮
     */
    private void updateButtonVisibility(boolean pauseButtonVisible, boolean stopButtonVisible, boolean skipButtonVisible) {
        pauseButton.setVisibility(pauseButtonVisible ? View.VISIBLE : View.GONE);
        stopButton.setVisibility(stopButtonVisible ? View.VISIBLE : View.GONE);
        skipButton.setVisibility(skipButtonVisible ? View.VISIBLE : View.GONE);
    }

    /**
     * 处理跳过逻辑
     */
    private void handleSkip() {
        Log.d(TAG, "handleSkip: " + (isFocusState ? "专注阶段" : "休息阶段") + " 执行跳过逻辑");

        // 直接切换状态，跳过当前阶段的剩余时间
        toggleState();

        // 检查任务是否已完成，如果已完成则不重新启动计时器
        if (currentCycle >= setting.getCycle() && !isFocusState) {
            isRunning = false;
            timerHandler.removeCallbacks(timerRunnable);
            return;
        }

        // 重新开始计时器
        if (!isRunning) {
            startTimer();
        }
    }

    /**
     * 处理任务完成逻辑
     */
    private void handleTaskCompletion() {
        Log.d(TAG, "handleTaskCompletion: 任务已完成，准备退出");
        // 记录专注数据
        recordFocusData(true);
        finish(); // 结束当前Activity，返回主界面
    }

    /**
     * 处理放弃逻辑
     */
    private void handleGiveUp() {
        Log.d(TAG, "handleGiveUp: 处理 放弃/返回/完成 逻辑");
        int elapsedTime; // 计算已进行的时间

        if (setting != null && TodoConstants.TIMER_MODE_COUNTDOWN.equals(setting.getTimerMode()))
            elapsedTime = getFocusDuration() - currentTime; // 倒计时模式，计算已用时间
        else
            elapsedTime = currentTime; // 正向计时模式，当前时间即为已用时间

        Log.d(TAG, "handleGiveUp: elapsedTime=" + elapsedTime + ", currentCycle=" + currentCycle);
        // 如果计时不超过5秒且没有已完成的周期
        if (elapsedTime <= 5 && currentCycle < 1) {
            // 时间太短，直接退出不记录
            Log.d(TAG, "handleGiveUp: 专注时间过短(" + elapsedTime + "秒)，不记录直接退出");
            // 停止计时器
            isRunning = false;
            timerHandler.removeCallbacks(timerRunnable);
            finish();
        } else { // 超过5秒，显示确认对话框
            // 停止计时器
            isRunning = false;
            timerHandler.removeCallbacks(timerRunnable);
            showGiveUpConfirmationDialog();
        }
    }

    /**
     * 处理正向计时模式下的停止逻辑
     */
    private void handleUptimeModeStop() {
        Log.d(TAG, "handleUptimeModeStop: 处理正向计时模式停止逻辑");
        int elapsedTime = currentFocusSeconds; // 正向计时模式，当前时间即为已用时间

        // 如果计时不超过5秒
        if (elapsedTime <= 5) {
            // 时间太短，直接退出不记录
            Log.d(TAG, "handleUptimeModeStop: 专注时间过短(" + elapsedTime + "秒)，不记录直接退出");
            // 停止计时器
            isRunning = false;
            timerHandler.removeCallbacks(timerRunnable);
            finish();
        } else {
            // 超过5秒，将当前专注时间累加到总专注时间
            Log.d(TAG, "handleUptimeModeStop: 专注时间超过5秒(" + elapsedTime + "秒)，进入休息状态");

            performTransition();

            // 累加当前专注时间到总时间
            totalFocusSeconds += elapsedTime;

            // 直接切换到休息状态
            isFocusState = false;
            statusText.setText("休息中");
            currentTime = getRestDuration(); // 休息状态始终是倒计时

            // 休息状态只显示跳过按钮
            updateButtonVisibility(false, false, true);

            // 确保计时器在休息状态下运行
            if (!isRunning) {
                startTimer();
            }
        }
    }

    /**
     * 显示放弃确认对话框
     * <br> 放弃也会被记录
     */
    private void showGiveUpConfirmationDialog() {
        // 实现放弃确认对话框
        new AlertDialog.Builder(this)
                .setTitle("确认退出")
                .setMessage("确定放弃后将会视为未完成")
                .setPositiveButton("确定", (dialog, which) -> {
                    Log.d(TAG, "showGiveUpConfirmationDialog: 用户选择确定，保存“未完成”记录");
                    recordFocusData(false);
                    finish(); // 结束当前Activity，返回主界面
                })
                .setNegativeButton("取消", (dialog, which) -> {
                    Log.d(TAG, "showGiveUpConfirmationDialog: 用户选择取消");
                    // 恢复计时
                    isRunning = true;
                    startTimer();
                    dialog.dismiss(); // 关闭对话框，继续当前专注
                })
                .setCancelable(true) // 点击外部区域可以关闭对话框
                .show();
    }

    /**
     * 执行状态切换时的过渡动画
     */
    private void performTransition() {
        Log.d(TAG, "performTransition: 执行状态切换过渡动画");

        // 显示过渡状态文本
        statusText.setText(isFocusState ? "专注结束" : "休息结束");

        // 执行振动反馈
        vibrate(isFocusState ? 500 : 800);

        // 创建一个简单的缩放动画作为过渡效果
        float originalScaleX = timerText.getScaleX();
        float originalScaleY = timerText.getScaleY();

        // 放大然后缩小的动画
        timerText.animate()
                .scaleX(1.2f)
                .scaleY(1.2f)
                .setDuration(300)
                .withEndAction(() -> {
                    timerText.animate()
                            .scaleX(originalScaleX)
                            .scaleY(originalScaleY)
                            .setDuration(300)
                            .start();
                })
                .start();

        // 同时改变背景颜色，提供更好的视觉反馈
        // 保存当前背景以便恢复
        GradientDrawable currentBackground = (GradientDrawable) focus_root.getBackground();

        // 创建过渡颜色（黄色）
        int[] transitionColors = {0xFFFFEB3B, 0xFFFFC107}; // 黄色渐变
        GradientDrawable.Orientation orientation = ColorUtils.getRandomOrientation();
        GradientDrawable transitionBackground = new GradientDrawable(orientation, transitionColors);
        transitionBackground.setGradientType(GradientDrawable.LINEAR_GRADIENT);

        // 应用过渡背景
        focus_root.setBackground(transitionBackground);

        try {
            sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        // 延迟时间后恢复原来的背景
        timerText.postDelayed(() -> {
            focus_root.setBackground(currentBackground);
            // 恢复正常状态文本
            if (!isTaskCompleted) {
                statusText.setText(isFocusState ? "专注中" : "休息中");
            }
        }, 1000);
    }

    /**
     * 记录专注数据
     *
     * @param isFinished 是否完成专注
     */
    private void recordFocusData(boolean isFinished) {
        Log.d(TAG, "recordFocusData: 开始记录专注数据, 完成状态: " + (isFinished ? "已完成" : "未完成"));

        // 设置记录的结束时间
        record.setEndTime(LocalDateTime.now());

        // 设置是否完成
        record.setFinished(isFinished);

        // 设置实际专注和休息秒数
        record.setActualFocusSeconds(totalFocusSeconds);
        record.setActualRestSeconds(totalRestSeconds);

        Log.d(TAG, "recordFocusData: 总专注时间=" + totalFocusSeconds + "秒, 总休息时间=" + totalRestSeconds + "秒");

        // 日志输出record字段
        Log.d(TAG, "recordFocusData: record={" +
                "\n\t\tclientCreatedAt: " + record.getClientCreatedAt() +
                "\n\t\tstartTime: " + record.getStartTime() +
                "\n\t\tendTime: " + record.getEndTime() +
                "\n\t\tfinished: " + record.getFinished() +
                "\n\t\tactualFocusSeconds: " + record.getActualFocusSeconds() +
                "\n\t\tactualRestSeconds: " + record.getActualRestSeconds() + 
                "\n\t\ttaskTitle: " + record.getTaskTitle() +
                "\n\t\ttaskType: " + record.getTaskType() +
                "\n\t\ttaskId: " + record.getTaskId() + "\n}");

        // TODO: 在这里可以将记录保存到数据库或发送到服务器
        saveRecordToPreferences(record);
    }

    /**
     * 将专注记录保存到SharedPreferences
     *
     * @param record 要保存的记录
     */
    private void saveRecordToPreferences(TodoRecordSyncDTO record) {
        RecordUtil.saveRecordToPreferences(this, record);
    }

    /**
     * 振动指定时间
     *
     * @param milliseconds 振动持续时间（毫秒）
     */
    private void vibrate(long milliseconds) {
        if (vibrator != null && vibrator.hasVibrator()) {
            VibrationEffect effect = VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE);
            vibrator.vibrate(effect);
            Log.d(TAG, "vibrate: 执行振动 " + milliseconds + " 毫秒");
        } else {
            Log.w(TAG, "vibrate: 设备不支持振动或未获取到振动器");
        }
    }
}
